﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufExtension.h"
#include "GnufItemEvents.h"
#include <unordered_map>
#include "GnufPallet.h"
#include "GnufQtObjectPtr.h"
#include <QPointer>

namespace gnuf
{
    class FamilyTypeButton;
    class List;
    class Check;
    class Text;
    class NameValuePairs;
    class QtViewTemplateManager;
    class QtTopToolBarSection;
    class QtLeftListWidgetSection;
    class QtRightTableSection;
    class GnufRightTableSection;
    class Info;
    class Toolbar;

    class GNUF_EXTENSION_EXPORT GnufNewTemplateDialog : public IItemEventHandler, public IPalletEventHandler
    {
        friend class QtNewTemplateDialog;
    public:
        GnufNewTemplateDialog();
        virtual ~GnufNewTemplateDialog();
        int popup(const std::wstring& caption);

        void setName(const std::wstring& name) { m_name = name; }
        std::wstring name() const { return m_name; };

        void setTypes(const std::vector<std::wstring>& types) { m_types = types; }
        void setTypesEnabled(bool is) { m_typeBoxEnabled = is; }

        void setCurrentType(int index) { m_currIndex = index; }
        void setCurrentText(const std::wstring& str) { m_currText = str; }
        int currentType() const { return m_currIndex; }

    protected:
        virtual bool onValiate(const std::wstring& text) { return true; }
        virtual void onHeaderButtonClicked(gnuf::Pallet* pPallet) override;
        virtual void onTextChanged(Text*) override;
        virtual void onCurrentIndexChanged(List*, int) override;
        virtual bool onFooterButtonClicked(Pallet*);

    private:
        gcmp::OwnerPtr<Toolbar> m_toolBar;
        gcmp::WeakPtr<NameValuePairs> m_nvps;
        std::wstring m_name;
        std::vector<std::wstring> m_types;
        int m_currIndex;
        bool m_typeBoxEnabled;
        std::wstring m_currText;
    };

    // RightTableCell自定义数据类型
    class GNUF_EXTENSION_EXPORT GnufTableCellCustomData
    {
    public:
        virtual ~GnufTableCellCustomData() {}
        virtual gcmp::OwnerPtr<GnufTableCellCustomData> Clone() const = 0;
    };

    class GNUF_EXTENSION_EXPORT GnufTableCellDialog : public IItemEventHandler, public IPalletEventHandler
    {
        friend class QtTableCellDialog;
    public:

        GnufTableCellDialog();
        virtual ~GnufTableCellDialog();

        int popup(const std::wstring& caption);
        void addItem(const std::wstring& label, double value);

        void setData(GnufTableCellCustomData* data);
        GnufTableCellCustomData* getData() { return m_data; }
        const GnufTableCellCustomData* getData() const { return m_data; }

        virtual void parseData() {}
    protected:
        GnufTableCellCustomData* m_data;
        virtual void onTextChanged(const std::wstring& label, const std::wstring& value) {}
        virtual bool onFooterButtonClicked(Pallet*) override { return true; }
        virtual void onHeaderButtonClicked(gnuf::Pallet* pPallet) override;
    private:
        virtual void onTextChanged(Text*) override;

        gcmp::OwnerPtr<Toolbar> m_toolBar;
        gcmp::WeakPtr<NameValuePairs> m_nvps;
        std::vector<std::pair<std::wstring, double>> m_items;
    };

    class GNUF_EXTENSION_EXPORT GnufViewTemplateSectionWatcher : public gcmp::WeakReferenceable
    {
        CANNOT_COPY_OR_ASSIGN(GnufViewTemplateSectionWatcher)
    public:
        GnufViewTemplateSectionWatcher() {}
        virtual void onDataChanged() {}
        virtual void onToolBarButtonClicked(ButtonEx* pButton) {}
        virtual void onListWidgetSizeChanged(int size) {}
    };

    class GNUF_EXTENSION_EXPORT GnufTopToolBarSection : public IItemEventHandler, public GnufViewTemplateSectionWatcher
    {
        friend class QtTopToolBarSection;
    public:
        GnufTopToolBarSection();
        virtual ~GnufTopToolBarSection();

        void addButton(const Info& info);
        void addWatcher(GnufViewTemplateSectionWatcher* pWatcher) { 
            m_watchers.push_back(gcmp::WeakPtr<GnufViewTemplateSectionWatcher>(pWatcher));
        }
    protected:
        virtual void onListWidgetSizeChanged(int) override;
        gcmp::OwnerPtr<Toolbar> m_toolBar;
    private:
        virtual void onClicked(Item*) override;
        QPointer<QtTopToolBarSection> m_qtItem;
        std::vector<gcmp::WeakPtr<GnufViewTemplateSectionWatcher>> m_watchers;
    };

    class GNUF_EXTENSION_EXPORT GnufRightTableSection : public IItemEventHandler, public gcmp::WeakReferenceable
    {
        friend class QtRightTableSection;
        friend class GnufViewTemplateManager;
        CANNOT_COPY_OR_ASSIGN(GnufRightTableSection)
    public:
        GnufRightTableSection();
        virtual ~GnufRightTableSection();

        struct TableCellData
        {
            enum DataType : std::uint8_t
            {
                Text,
                List,
                Check,
                Button
            };

            struct ListData
            {
                ListData(int index = 0, const std::vector<std::wstring>& infos = {}) : Index(index), ListInfos(infos) {}
                int Index = 0;
                std::vector<std::wstring> ListInfos;
            };

            TableCellData(const DataType& type, const std::wstring& text) : Type(type), TextCellData(text), CheckState(false), Editable(true) {}
            TableCellData(const DataType& type, const std::wstring& text, bool editable) : Type(type), TextCellData(text), CheckState(false), Editable(editable) {}
            TableCellData(const DataType& type, const ListData& listCellData) : Type(type), ListCellData(listCellData), CheckState(false), Editable(false) {}
            TableCellData(const DataType& type, bool checked) : Type(type), CheckState(checked), Editable(false) {}

            TableCellData(const TableCellData &src)
            {
                this->Type = src.Type;
                this->TextCellData = src.TextCellData;
                this->ListCellData = src.ListCellData;
                this->CheckState = src.CheckState;
                this->Editable = src.Editable;
                if (src.CustomData)
                    this->CustomData = TransferOwnership(src.CustomData->Clone());
            }

            TableCellData & operator = (const TableCellData &src)
            {
                this->Type = src.Type;
                this->TextCellData = src.TextCellData;
                this->ListCellData = src.ListCellData;
                this->CheckState = src.CheckState;
                this->Editable = src.Editable;
                if (src.CustomData)
                    this->CustomData = TransferOwnership(src.CustomData->Clone());
                return *this;
            }

            DataType Type;
            std::wstring TextCellData;
            ListData ListCellData;
            bool CheckState = false;
            bool Editable = false;
            gcmp::OwnerPtr<GnufTableCellCustomData> CustomData;
        };

        typedef std::vector<TableCellData> TableRowData;
        typedef std::vector<TableRowData> TableGroupData;
        void setTabelData(const std::vector<TableRowData>& datas);
        void setHeaderInfo(const std::vector<std::wstring>& info) { m_headerInfo = info; }
        void addWatcher(GnufViewTemplateSectionWatcher* pWatcher) { 
            m_watchers.push_back(gcmp::WeakPtr<GnufViewTemplateSectionWatcher>(pWatcher));
        }
        const std::vector<TableRowData>& tabelDatas() const { return m_tabelDatas; }
        void setTableObjectName(const std::wstring& val);
        std::wstring tableObjectName() { return m_tableObjectName; }

    protected:
        virtual void onCurrentIndexChanged(List*, int) override;
        virtual void onCheckStatusChanged(int row, int column, bool);
        virtual void onGetInitialTableDatas() = 0;
        virtual void onDialogButtonClicked(int row,int column, gcmp::OwnerPtr<GnufTableCellCustomData> &data) {}
        virtual void onClicked(Item* item) override;

    private:
        void disconnectFromQtWidget();
        std::vector<std::wstring> m_headerInfo;
        std::vector<gcmp::WeakPtr<GnufViewTemplateSectionWatcher>> m_watchers;
        std::vector<gcmp::OwnerPtr<Toolbar>> m_listToolBars;
        std::vector<gcmp::OwnerPtr<Toolbar>> m_buttonToolBars;
        QPointer<QtRightTableSection> m_qtItem;
        std::wstring m_tableObjectName;
        TableGroupData m_tabelDatas;
    };

    class GNUF_EXTENSION_EXPORT GnufLeftListWidgetSection : public IItemEventHandler, public GnufViewTemplateSectionWatcher
    {
        friend class QtLeftListWidgetSection;
        friend class GnufViewTemplateManager;
    public:
        GnufLeftListWidgetSection();
        virtual ~GnufLeftListWidgetSection();

        typedef std::vector<std::wstring> ViewTemplateItems;
        typedef std::vector<std::pair<std::wstring, ViewTemplateItems>> ViewTemplateGroup;

        void setViewTemplateGroupDatas(const ViewTemplateGroup& datas);
        const ViewTemplateGroup& getViewTemplateGroupDatas() const { return m_viewTemplateGroup; }

        void setRightTableSectonData(GnufRightTableSection* pRightTableSection);
        void setCurrentGroup(int index);
        int currentGroup() const;
        std::wstring currentGroupName() const;

        void setCurrentItem(int index, bool refresh = true);
        int currentItem() const { return m_currentItem; }
        std::wstring currentItemName() const;

        const std::unordered_map<std::wstring, GnufRightTableSection::TableGroupData>& totalData() const { return m_totalData; }
        void addWatcher(GnufViewTemplateSectionWatcher* pWatcher) {
            m_watchers.push_back(gcmp::WeakPtr<GnufViewTemplateSectionWatcher>(pWatcher));
        }

    protected:
        virtual void onGetCurrentItemData(GnufRightTableSection::TableGroupData& data) {}
        virtual void onGetViewTemplateGroupInfos() = 0;
        virtual void onToolBarButtonClicked(ButtonEx* pButton) override {};
        virtual void onDataChanged() override;
        virtual void onCurrentIndexChanged(List*, int) override;
        virtual void onCurrentItemChanged(int, int);

        void switchTableDatas();
        void markListWidgetSizeChanged();
        gcmp::WeakPtr<GnufRightTableSection> m_rightTableSection;
        ViewTemplateGroup m_viewTemplateGroup;
        std::unordered_map<std::wstring, GnufRightTableSection::TableGroupData> m_totalData;

    private:
        gcmp::OwnerPtr<Toolbar> m_toolBar;
        List*  m_switcher;
        QPointer<QtLeftListWidgetSection> m_qtItem;
        int m_currentItem;
        std::vector<gcmp::WeakPtr<GnufViewTemplateSectionWatcher>> m_watchers;
    };

    class GNUF_EXTENSION_EXPORT GnufViewTemplateManager : public IPalletEventHandler
    {
    public:
        GnufViewTemplateManager();
        virtual ~GnufViewTemplateManager();

        void setTopToolBar(GnufTopToolBarSection* data) { m_topToolBarSection = data; }
        GnufTopToolBarSection* getTopToolBarData() { return m_topToolBarSection.Get(); }

        void setLeftTreeWidget(GnufLeftListWidgetSection* data) { m_leftTreeWidgetSection = data; }
        GnufLeftListWidgetSection* getLeftTreeWidgetData() { return m_leftTreeWidgetSection.Get(); }

        void setRightTabelSection(GnufRightTableSection* data) { m_rightTabelSection = data; }
        GnufRightTableSection* getRightTabelSectionData() { return m_rightTabelSection.Get(); }

        int popup(const std::wstring& caption);

        static std::wstring getLastSelectedItemName() { return s_lastSelectedItemName; }
        static std::wstring getLastSelectedGroupName() { return s_lastSelectedGroupName; }

    protected:
        virtual bool onFooterButtonClicked(Pallet*) override { return true; }
        virtual void onHeaderButtonClicked(gnuf::Pallet* pPallet) override;


    private:
        gcmp::WeakPtr<GnufTopToolBarSection> m_topToolBarSection;
        gcmp::WeakPtr<GnufLeftListWidgetSection> m_leftTreeWidgetSection;
        gcmp::WeakPtr<GnufRightTableSection> m_rightTabelSection;
        static std::wstring s_lastSelectedItemName;
        static std::wstring s_lastSelectedGroupName;
    };
}
